package com.xinchao.job;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class JobManager {
	private Logger logger = LoggerFactory.getLogger(JobManager.class);
	@Autowired
	private Scheduler scheduler;
	
	/**
	 * 新建一个job任务
	 * @param jobName 任务
	 * @param jobGroupName 任务组名
	 * @param triggerName 触发器名
	 * @param triggerGroupName 触发器组名
	 * @param className 任务类
	 * @param cron 时间设置
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String jobClassName,
			String cron) {
		try {
			Class jobClass = Class.forName(jobClassName);
			jobClass.newInstance();
			
			// 任务名，任务组，任务执行类
			JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();

			// 触发器
			TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
			
			// 触发器名、触发器组、触发器时间设定
			triggerBuilder.withIdentity(triggerName, triggerGroupName);
			triggerBuilder.startNow();
			triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
			
			// 创建Trigger对象
			CronTrigger trigger = (CronTrigger) triggerBuilder.build();

			// 调度容器设置JobDetail和Trigger
			scheduler.scheduleJob(jobDetail, trigger);

			// 启动
			if (!scheduler.isShutdown()) {
				scheduler.start();
			}
			logger.info("添加【"+jobName+"】job任务成功：");
		} catch (Exception e) {
			logger.error("创建【"+jobName+"】job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 修改一个任务的触发时间
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 * @param cron
	 */
	public void updateJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
			String cron) {
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(cron)) {
				/** 方式一 ：调用 rescheduleJob 开始 */
				// 触发器
				TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
				// 触发器名,触发器组
				triggerBuilder.withIdentity(triggerName, triggerGroupName);
				triggerBuilder.startNow();
				// 触发器时间设定
				triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
				// 创建Trigger对象
				trigger = (CronTrigger) triggerBuilder.build();
				/** 方式一 ：修改一个任务的触发时间 */
				scheduler.rescheduleJob(triggerKey, trigger);
				/** 方式一 ：调用 rescheduleJob 结束 */

				/** 方式二：先删除，然后在创建一个新的Job */
				// JobDetail jobDetail = scheduler.getJobDetail(JobKey.jobKey(jobName,jobGroupName));
				// Class<? extends Job> jobClass = jobDetail.getJobClass();
				// removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
				// addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
				/** 方式二 ：先删除，然后在创建一个新的Job */
				logger.info("更新【"+jobName+"】job任务成功：");
			}
		} catch (Exception e) {
			logger.error("更新【"+jobName+"】job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 新建或者更新一个job任务
	 * @param jobName 任务
	 * @param jobGroupName 任务组名
	 * @param triggerName 触发器名
	 * @param triggerGroupName 触发器组名
	 * @param className 任务类
	 * @param cron 时间设置
	 */
	public void addOrUpdateJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String jobClassName,
			String cron) {
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			if (trigger == null) {
				this.addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClassName, cron);
			}else {
				this.updateJob(jobName, jobGroupName, triggerName, triggerGroupName, cron);
			}
		} catch (SchedulerException e) {
			logger.error("添加/更新【"+jobName+"】job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description: 移除一个任务
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 */
	public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

			scheduler.pauseTrigger(triggerKey);// 停止触发器
			scheduler.unscheduleJob(triggerKey);// 移除触发器
			scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
		} catch (Exception e) {
			logger.error("移除【"+jobName+"】job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:启动所有定时任务
	 */
	public void startJobs() {
		try {
			scheduler.start();
		} catch (Exception e) {
			logger.error("启动所有job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:关闭所有定时任务
	 */
	public void shutdownJobs() {
		try {
			if (!scheduler.isShutdown()) {
				scheduler.shutdown();
			}
		} catch (Exception e) {
			logger.error("关闭所有job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * @Description:关闭所有定时任务
	 */
	public void run() {
		try {
			boolean init = true;
			for (String groupName : scheduler.getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                	init = false;
                    String jobName = jobKey.getName();
                    String jobGroup = jobKey.getGroup();
                    logger.info("[jobName] : " + jobName + " [groupName] : "  + jobGroup);
                }
			}
			if ( init ) {
				this.init();
			} else {
				this.startJobs();
			}
		} catch (Exception e) {
			logger.error("获取当前所有job任务信息异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * @Description:初始化自定义job
	 */
	public void init() {
		try {
			this.addOrUpdateJob("check-job", "xcm", "check-job-trigger","xcm", "com.xinchao.job.task.CheckJob", "0/5 * * * * ?");
		} catch (Exception e) {
			logger.error("check-job任务异常：" + e.getMessage(),e);
			throw new RuntimeException(e);
		}
	}
	
	
	public JobManager() {
		super();
	}
	
}
